using System;
using System.Collections.Generic;
using System.Text;
using Sandia.MVCFramework.Request;

namespace Sandia.MVCFramework.Request
{
    /// <summary>
    /// A generic that creates requests that takes two parameters
    /// </summary>
    /// <remarks>
    /// This generic simplifies the creation both of the request and the underlying parameter types.
    /// It uses the ObjectParameter to create those types.  So you simply have to specify the object
    /// types that get stored as parameters and (if desired) expose the accessors using semantically
    /// meaningful names.
    /// </remarks>
    /// <typeparam name="T">The first type to be stored as a parameter</typeparam>
    /// <typeparam name="R">The second type to be stored as a parameter</typeparam>
    /// <typeparam name="S">The third type to be stored as a parameter</typeparam>
    public class ThreeParameterRequest<T, R, S>: AbstractStandardRequest
    {
        /// <summary>
        /// Create a new request
        /// </summary>
        /// <param name="p1">The first object to be stored as a parameter</param>
        /// <param name="p2">the second object to be stored as a parameter</param>
        /// <param name="p3">The third object to be stored as a parameter</param>
        public ThreeParameterRequest(T p1, R p2, S p3)
        {

            parameters["p1"] = new ObjectParameter<T>(p1);
            parameters["p2"] = new ObjectParameter<R>(p2);
            parameters["p3"] = new ObjectParameter<S>(p3);
        }

        /// <summary>
        /// Accessor for the first type
        /// </summary>
        /// <remarks>
        /// Expose publicly in a subclass using a semantically meaningful name.
        /// </remarks>
        protected T Param1
        {
            get { return (T)parameters["p1"].Data; }
            set { parameters["p1"] = new ObjectParameter<T>(value); }
        }

        /// <summary>
        /// Accessor for the second type
        /// </summary>
        /// <remarks>
        /// Expose publicly in a subclass using a semantically meaningful name.
        /// </remarks>
        protected R Param2
        {
            get { return (R)parameters["p2"].Data; }
            set { parameters["p2"] = new ObjectParameter<R>(value); }
        }

        /// <summary>
        /// Accessor for the third type
        /// </summary>
        /// <remarks>
        /// Explicitly explos in a subclass using a semantically meaningful name.
        /// </remarks>
        protected S Param3
        {
            get { return (S)parameters["p3"].Data; }
            set { parameters["p3"] = new ObjectParameter<S>(value); }
        }

        /// <summary>
        /// Initialize both parameters to null
        /// </summary>
        protected override void initParameters()
        {
            parameters["p1"] = null;
            parameters["p2"] = null;
            parameters["p3"] = null;
        }
    }
}
